/* Reflect api */
const { log } = console
// 1. Reflect.apply(target, thisArg, args) thisArg对象调用target函数传递args参数是[]
let f1 = () => {
  function fn(a, b) {
    return a + b
  }
  let res = Reflect.apply(fn, null, [1, 2])
  log(res) // 3
  // 调用Math.max()
  let max = Reflect.apply(Math.max, null, [2, 3, 4, 5])
  log(max) // 5
}
// f1()

// 2. Reflect.construct(target, args) 使用函数target创建对象，传递参数[args]
let f2 = () => {
  function Student(id, name, age) {
    this.name = name
    this.id = id
    this.age = age
  }
  let obj = Reflect.construct(Student, [1, 'tom', 20])
  log(obj) // Student { name: 'tom', id: 1, age: 20 }
}

// 3. Reflect.get(target, name, receiver) 获得对象target属性name的值
let f3 = () => {
  let stu = { name: 'tom', id: 1, age: 20 }
  let id = Reflect.get(stu, 'id')
  log(`id=${id}`) // id=1
}

// 4. Reflect.set(target, name, value, receiver) 设置对象target属性name的值
let f4 = () => {
  let stu = { name: 'tom', id: 1, age: 20 }
  Reflect.set(stu, 'id', 2)
  Reflect.set(stu, 'gender', '男')
  log(`id=${stu.id}，gender=${stu.gender}`) // id=2，gender=男
}

// 5. Reflect.defineProperty(target, name, desc) 定义对象target属性name指定描述器desc
let f5 = () => {
  let stu = { name: 'tom', id: 1, age: 20 }
  Reflect.defineProperty(stu, 'gender', {
    value: '男',
    configurable: true,
    writable: true,
    enumerable: true,
  })
  log(stu) // { name: 'tom', id: 1, age: 20, gender: '男' }
}

// 6. Reflect.has(target, name) 判断对象target是否有属性name
let f6 = () => {
  let stu = { name: 'tom', id: 1, age: 20 }
  let rt = Reflect.has(stu, 'gender')
  log(rt) // false stu对象没有gender属性
}

// 7. Reflect.ownKeys(target) 获得对象target的所有属性列表
let f7 = () => {
  let stu = { name: 'tom', id: 1, age: 20, [Symbol()]: '男' }
  let list = Reflect.ownKeys(stu)
  for (let item of list) {
    log(item) // name id age Symbol()
  }
}

// 8. Reflect.isExtensible(target) 对象target是否可扩展, 是否可额外添加属性
let f8 = () => {
  let stu = { name: 'tom', id: 1, age: 20, [Symbol()]: '男' }
  let rt = Reflect.isExtensible(stu)
  log(`stu对象是可扩展的的吗:${rt}`) // stu对象是可扩展的的吗:true
  Object.freeze(stu) // 冻结对象stu,对象的属性不可操作
  stu.age = 21
  log(stu) // { name: 'tom', id: 1, age: 20, [Symbol()]: '男' }
  rt = Reflect.isExtensible(stu)
  log(`stu对象是可扩展的的吗:${rt}`) // stu对象是可扩展的的吗:false
}

// 9. Reflect.preventExtensions(target) 阻止对象的扩展，阻止额外添加属性
let f9 = () => {
  let stu = { name: 'tom', id: 1, age: 20, [Symbol()]: '男' }
  Reflect.preventExtensions(stu) // { name: 'tom', id: 1, age: 21, [Symbol()]: '男' }
  stu.gender = '女'
  // 删除对象stu属性id
  Reflect.deleteProperty(stu, 'id')
  log(stu) // { name: 'tom', id: 1, age: 20, [Symbol()]: '男' }
  log(Reflect.isExtensible(stu)) // false
}

// 10. Reflect.getOwnPropertyDescriptor(target, name) 获得target对象属性name的属性描述器
let f10 = () => {
  let stu = { name: 'tom', id: 1, age: 20, [Symbol()]: '男' }
  let descriptor = Reflect.getOwnPropertyDescriptor(stu, 'id')
  log(descriptor) // { value: 1, writable: true, enumerable: true, configurable: true }
}

// 11. Reflect.getPrototypeOf(target) 获得target对象的原型对象
// Reflect.setPrototypeOf(target, prototype) 设置target对象的原型对象
let f11 = () => {
  let proto = {
    info() {
      log(this)
    },
  }
  let stu = { name: 'tom', id: 1, age: 20, [Symbol()]: '男' }
  Reflect.setPrototypeOf(stu, proto)
  stu.info() // { name: 'tom', id: 1, age: 20, [Symbol()]: '男' }
  log(Reflect.getPrototypeOf(stu) === proto) // true
}
f11()
